<?php

namespace Packages\Upload\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use OSS\Core\OssException;
use OSS\OssClient;

class UploadController extends Controller
{
    private $ossClient;

    private $bucket;

    private $ossUrl;

    public function __construct()
    {
        // 配置信息
        $this->bucket = env('ALIOSS_BUCKET');
        $this->ossUrl = 'https://' . env('ALIOSS_BUCKET') . '.' . env('ALIOSS_END_POINT');
        // 初始化
        $this->ossClient = new OssClient(env('ALIOSS_ACCESS_KEY_ID'), env('ALIOSS_ACCESS_KEY_SECRET'), env('ALIOSS_END_POINT'));
    }

    /**
     * 获取alioss上传凭证
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getAliOSSPolicy(Request $request)
    {
        // 定义业务参数验证规则 验证参数
        $params = $this->validateParams($request, [
            'file_dir' => 'string|max:32',
        ]);

        $file_dir = $params['file_dir'] ?? 'default';

        $res = app('uploadService')->genPolicy($file_dir);

        return $this->returnResponse($res);
    }

    /**
     * 验证图片是否合法
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function checkImage(Request $request)
    {

        $res = app('wxService')->checkImage($request);

        if ($res['status']) {
            return response()->json(['serverTime' => time(), 'ServerNo' => 200, 'ResultData' => $res['msg']]);
        } else {
            return response()->json(['serverTime' => time(), 'ServerNo' => 400, 'ResultData' => $res['msg']]);
        }
    }

    /**
     * alioss回调
     *
     * @param Request $request
     */
    public function notify(Request $request)
    {
        app('uploadService')->callback($request);
    }

    /**
     * 获取文件列表
     * @param Request $request
     * @return JsonResponse
     */
    public function getOssList(Request $request): JsonResponse
    {
        // 定义业务参数验证规则 验证参数
        $params = $this->validateParams($request, [
            'prefix' => 'string',
            'ossMaxKeys' => 'required|integer',
            'ossMarker' => 'string',
        ]);

        $options = array(
            'prefix' => $params['prefix'],
            OssClient::OSS_MAX_KEYS => $params['ossMaxKeys'],
            OssClient::OSS_MARKER => $params['ossMarker']
        );

        try {
            $listObjectInfo = $this->ossClient->listObjects($this->bucket, $options);
        } catch (OssException $e) {
            Log::info($e->getMessage());
            return $this->returnErrorResponse($e->getMessage(), '40000');
        }

        $data = [];
        // 获取文件列表。
        $objectList = $listObjectInfo->getObjectList();
        if (!empty($objectList)) {
            foreach ($objectList as $objectInfo) {
                $path = $objectInfo->getKey();
                if ($path != $options['prefix']) {
                    $array = explode('/', $objectInfo->getKey());
                    $item = [
                        'dir' => false,
                        'name' => end($array),
                        'timeModified' => $objectInfo->getLastModified(),
                        'path' => $path,
                        'url' => $this->ossUrl . '/' . $path,
                        'size' => $objectInfo->getSize()
                    ];
                    $data[] = $item;
                }
            }
        }
        // 获取目录列表
        $prefixList = $listObjectInfo->getPrefixList();
        if (!empty($prefixList)) {
            foreach ($prefixList as $prefixInfo) {
                $array = $options['prefix'] ? explode($options['prefix'], $prefixInfo->getPrefix()) : [$prefixInfo->getPrefix()];
                $item = [
                    'dir' => true,
                    'name' => end($array),
                    'path' => $prefixInfo->getPrefix(),
                ];
                $data[] = $item;
            }
        }
        return $this->returnResponse(['list' => $data, 'next' => $listObjectInfo->getNextMarker(), 'is_end' => $listObjectInfo->getIsTruncated() === 'false']);
    }

    /**
     * 删除文件
     * @param Request $request
     * @return JsonResponse
     */
    public function delOssFile(Request $request): JsonResponse
    {
        // 定义业务参数验证规则 验证参数
        $params = $this->validateParams($request, [
            'path' => 'required',
            'type' => 'required',
        ]);

        $type = $params['type'];
        $path = $params['path'];
        if ($type == 1) {
            // 数组多个删除
            if (is_array($path)) {
                $this->ossClient->deleteObjects($this->bucket, $path);
            } else {
                $this->ossClient->deleteObject($this->bucket, $path);
            }
        } else {
            if (!is_string($path)) {
                return $this->returnErrorResponse('参数不正确', '40004');
            }
            try {
                $option = array(
                    OssClient::OSS_MARKER => null,
                    'delimiter' => '',
                    // 如果您需要删除所有前缀为src的文件，则prefix设置为src。设置为src后，所有前缀为src的非目录文件、src目录以及目录下的所有文件均会被删除。
                    OssClient::OSS_PREFIX => $path,
                );
                $bool = true;
                while ($bool) {
                    // 列举并删除多个文件。
                    $result = $this->ossClient->listObjects($this->bucket, $option);
                    $objects = array();
                    if (count($result->getObjectList()) > 0) {
                        foreach ($result->getObjectList() as $key => $info) {
                            $objects[] = $info->getKey();
                        }
                        $delObjects = $this->ossClient->deleteObjects($this->bucket, $objects);
                    }

                    if ($result->getIsTruncated() === 'true') {
                        $option[OssClient::OSS_MARKER] = $result->getNextMarker();
                    } else {
                        $bool = false;
                    }
                }
            } catch (OssException $e) {
                Log::info('OSS删除文件出错：' . $e->getMessage());
                return $this->returnErrorResponse($e->getMessage(), '40000');
            }
        }
        return $this->returnResponse();
    }
}
